package com.duolebo.uteped_sdk.db;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import com.duolebo.uteped_sdk.model.HeartRateModel;
import com.duolebo.uteped_sdk.model.SleepModel;
import com.duolebo.uteped_sdk.model.Spo2Model;
import com.duolebo.uteped_sdk.model.StepModel;
import com.duolebo.uteped_sdk.model.StressModel;
import com.duolebo.uteped_sdk.model.WorkoutModel;
import com.duolebo.uteped_sdk.utils.Const;
import com.duolebo.uteped_sdk.utils.SPHelper;
import com.yc.nadalsdk.bean.FitnessData;
import com.yc.nadalsdk.bean.FitnessHeartRateData;
import com.yc.nadalsdk.bean.FitnessOxygenData;
import com.yc.nadalsdk.bean.FitnessStepData;
import com.yc.nadalsdk.bean.SleepData;
import com.yc.nadalsdk.bean.StressData;
import com.yc.nadalsdk.bean.WorkoutData;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: LiuYang
 * @Date: 2023/12/20 11:46
 * @Description:
 */
public class UTEPedDb extends SampleDB {
    private static final String TAG = "UTEPedDb";
    public static final String DB_NAME = "uteped_db.db";
    public static final int DB_VERSION = 1;
    public static final String SLEEP_TABLE = "sleep";
    public static final String STRESS_TABLE = "stress";
    public static final String HART_RATE_TABLE = "heart_rate";
    public static final String SPO2_TABLE = "spo2";
    public static final String STEP_TABLE = "step";
    public static final String WORKOUT_TABLE = "workout";

    private static UTEPedDb instance;

    public static UTEPedDb getInstance(Context context) {
        if (instance == null) {
            String dbName = SPHelper.shareInstance().getString(Const.M_useDatabaseByName, "");
            if (TextUtils.isEmpty(dbName)) {
                instance = new UTEPedDb(context);
            }
            else {
                instance = new UTEPedDb(context, dbName, UTEPedDb.DB_VERSION);
            }
        }
        return instance;
    }

    public static UTEPedDb shareInstance() {
        return instance;
    }

    public UTEPedDb(Context context, String dbName, int version) {
        super(context, dbName, version);

        Table table;
        //add tables
        table = new Table(SLEEP_TABLE, SleepModel.class, this);
        putTable(SLEEP_TABLE, table);

        table = new Table(STRESS_TABLE, StressModel.class, this);
        putTable(STRESS_TABLE, table);

        table = new Table(HART_RATE_TABLE, HeartRateModel.class, this);
        putTable(HART_RATE_TABLE, table);

        table = new Table(SPO2_TABLE, Spo2Model.class, this);
        putTable(SPO2_TABLE, table);

        table = new Table(WORKOUT_TABLE, WorkoutModel.class, this);
        putTable(WORKOUT_TABLE, table);

        table = new Table(STEP_TABLE, StepModel.class, this);
        putTable(STEP_TABLE, table);
    }

    /**
     * SampleDB
     *
     * @param context context
     */
    public UTEPedDb(Context context) {
        this(context, DB_NAME, DB_VERSION);
    }

    public void saveFitnessData(FitnessData fitnessData, int startTime, int endTime, String address) {
        List<FitnessOxygenData> oxygenData = fitnessData.getOxygenData();
        List<FitnessStepData> stepData = fitnessData.getStepData();
        List<FitnessHeartRateData> heartRateData = fitnessData.getHeartRateData();

        if (!oxygenData.isEmpty()) {
            this.getTable(UTEPedDb.SPO2_TABLE).delete2(getDeleteWhereCause(startTime, endTime, address));
            List<Spo2Model> spo2ModelList = new ArrayList<>(oxygenData.size());
            for (FitnessOxygenData data : oxygenData) {
                Spo2Model spo2Model = new Spo2Model(data);
                spo2Model.setAddress(address);
                spo2ModelList.add(spo2Model);
            }
            this.getTable(UTEPedDb.SPO2_TABLE).insert(spo2ModelList);
            Log.d(TAG, "saveSpo2Data data size:" + spo2ModelList.size());
        }

        if (!stepData.isEmpty()) {
            this.getTable(UTEPedDb.STEP_TABLE).delete2(getDeleteWhereCause(startTime, endTime, address));

            List<StepModel> stepModelList = new ArrayList<>(stepData.size());
            for (FitnessStepData data : stepData) {
                StepModel stepModel = new StepModel(data);
                stepModel.setAddress(address);
                stepModelList.add(stepModel);
            }
            this.getTable(UTEPedDb.STEP_TABLE).insert(stepModelList);
            Log.d(TAG, "saveStepData data size:" + stepModelList.size());
        }

        if (!heartRateData.isEmpty()) {
            this.getTable(UTEPedDb.HART_RATE_TABLE).delete2(getDeleteWhereCause(startTime, endTime, address));

            List<HeartRateModel> hrModels = new ArrayList<>(heartRateData.size());
            for (FitnessHeartRateData data : heartRateData) {
                HeartRateModel heartRateModel = new HeartRateModel(data);
                heartRateModel.setAddress(address);
                hrModels.add(heartRateModel);
            }
            this.getTable(UTEPedDb.HART_RATE_TABLE).insert(hrModels);
            Log.d(TAG, "saveHearRateData data size:" + hrModels.size());
        }
    }

    public void saveSleepData(List<SleepData> sleepData, int startTime, int endTime, String address) {
        if (sleepData.isEmpty()) {
            Log.d(TAG, "sleepData is empty");
            return;
        }
        this.getTable(UTEPedDb.SLEEP_TABLE).delete2(getDeleteWhereCause(startTime, endTime, address));

        List<SleepModel> sms = new ArrayList<>(sleepData.size());
        for (SleepData data : sleepData) {
            SleepModel model = new SleepModel(data);
            model.setAddress(address);
            sms.add(model);
        }
        this.getTable(UTEPedDb.SLEEP_TABLE).insert(sms);
        Log.d(TAG, "saveSleepData data size:" + sms.size());
    }

    public void saveStressData(List<StressData> stressData, int startTime, int endTime, String address) {
        if (stressData.isEmpty()) {
            Log.d(TAG, "stressData is empty");
            return;
        }
        this.getTable(UTEPedDb.STRESS_TABLE).delete2(getDeleteWhereCause(startTime, endTime, address));

        List<StressModel> sms = new ArrayList<>(stressData.size());
        for (StressData data : stressData) {
            StressModel model = new StressModel(data);
            model.setAddress(address);
            sms.add(model);
        }
        this.getTable(UTEPedDb.STRESS_TABLE).insert(sms);
        Log.d(TAG, "saveStressData data size:" + sms.size());
    }

    public void saveWorkoutData(List<WorkoutData> workoutData, int startTime, int endTime, String address) {
        if (workoutData.isEmpty()) {
            Log.d(TAG, "saveWorkoutData is empty");
            return;
        }

        String sql = "calendar >= ? and calendar <= ? and address = ? and (sport_id is null or sport_id = 0)";
        String [] args = new String[] {formatDate(startTime), formatDate(endTime), address};
        this.getTable(UTEPedDb.WORKOUT_TABLE).delete(sql, args);

        List<WorkoutModel> sms = new ArrayList<>(workoutData.size());
        for (WorkoutData data : workoutData) {
            WorkoutModel model = new WorkoutModel(data);
            model.setAddress(address);
            sms.add(model);
        }
        this.getTable(UTEPedDb.WORKOUT_TABLE).insert(sms);
        Log.d(TAG, "saveWorkoutData data size:" + sms.size());
    }

    @NonNull
    private static Map<String, String> getDeleteWhereCause(int startTime, int endTime, String address) {
        Map<String, String> whereMap = new HashMap<>(3);
        whereMap.put("calendar >= ?", formatDate(startTime));
        whereMap.put("calendar <= ?", formatDate(endTime));
        whereMap.put("address = ?", address);
        return whereMap;
    }

    @NonNull
    private static Map<String, String> getDeleteCause(int startTime, int endTime, String address) {
        Map<String, String> whereMap = new HashMap<>(3);
        whereMap.put("date_created >= ?", startTime + "");
        whereMap.put("date_created < ?", endTime + "");
        whereMap.put("address = ?", address);
        return whereMap;
    }

    private static String formatDate(int timestamp) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        return sdf.format(new Date(timestamp * 1000L));
    }

    public void removeData(String address) {
        try {
            Map<String, String> whereMap = new HashMap<>(1);
            whereMap.put("address", address);
            try {
                this.getTable(UTEPedDb.HART_RATE_TABLE).delete(whereMap);
                this.getTable(UTEPedDb.SPO2_TABLE).delete(whereMap);
                this.getTable(UTEPedDb.STEP_TABLE).delete(whereMap);
                this.getTable(UTEPedDb.SLEEP_TABLE).delete(whereMap);
                this.getTable(UTEPedDb.STRESS_TABLE).delete(whereMap);
                this.getTable(UTEPedDb.WORKOUT_TABLE).delete(whereMap);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
